﻿using System;
using System.IO;

namespace ArgusLib
{
	public class TempDirectoryDeleteException : Exception
	{
		public TempDirectoryDeleteException(string message, Exception innerException)
			:base(message, innerException){}
	}

	public class TempDirectory : IDisposable
	{
		int fileIndex;

		public DirectoryInfo DirectoryInfo { get; private set; }
		public string Path { get { return this.DirectoryInfo.FullName; } }

		TempDirectory(DirectoryInfo directoryInfo)
		{
			this.DirectoryInfo = directoryInfo;
			this.fileIndex = 0;
		}

		TempDirectory(string path)
			: this(new DirectoryInfo(path)) { }

		/// <summary>
		/// Creates a temporary directory which will be deleted when the <see cref="TempDirectory"/>
		/// is disposed.
		/// </summary>
		public static TempDirectory Create()
		{
			return TempDirectory.Create(System.Environment.CurrentDirectory);
		}

		/// <summary>
		/// Creates a temporary directory which will be deleted when the <see cref="TempDirectory"/>
		/// is disposed.
		/// </summary>
		/// <param name="tempPath">The base directory in which the new temp directory will be created.</param>
		public static TempDirectory Create(string tempPath)
		{
			DirectoryInfo tempDir = new DirectoryInfo(tempPath);
			string appname = System.IO.Path.GetFileNameWithoutExtension(System.Environment.GetCommandLineArgs()[0]);
			appname = appname.RemoveChars(System.IO.Path.GetInvalidPathChars());
			if (string.IsNullOrEmpty(appname) == true)
				appname = "ArgusLib " + ArgusLib.Environment.ArgusLibVersion.ToString();

			DirectoryInfo RetVal = tempDir.CombineDirectory(appname);
			for (int i = 1; i < int.MaxValue; i++)
			{
				if (RetVal.Exists == false)
					break;
				RetVal = tempDir.CombineDirectory(appname + " (" + i.ToString() + ')');
			}
			RetVal.Create();
			return new TempDirectory(RetVal);
		}

		public FileInfo GetTempFile()
		{
			return this.GetTempFile(string.Empty);
		}

		public FileInfo GetTempFile(string extension)
		{
			return this.DirectoryInfo.CombineFile((this.fileIndex++).ToString() + extension);
		}

		public DirectoryInfo GetSubdirectory(string directoryName)
		{
			DirectoryInfo RetVal = this.DirectoryInfo.CombineDirectory(directoryName);
			if (RetVal != null)
				RetVal.Create();
			return RetVal;
		}

		~TempDirectory()
		{
			this.Dispose();
		}

		public void Dispose()
		{
			if (Directory.Exists(this.Path) == true)
			{
				try { this.DirectoryInfo.Delete(true); }
				catch (Exception e) { throw new TempDirectoryDeleteException("The temporary directory could be deleted.", e); }
			}
		}

		public void Delete()
		{
			this.Dispose();
		}

		public override string ToString()
		{
			return this.Path;
		}
	}
}
